package com.zixi.ai.file.service.impl;

import cn.hutool.core.date.DateUtil;
import com.zixi.ai.common.utils.StringUtils;
import com.zixi.ai.common.utils.file.MimeTypeUtils;
import com.zixi.ai.config.properties.FileProperties;
import com.zixi.ai.file.service.IFileService;
import io.minio.*;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Strings;
import org.apache.commons.text.RandomStringGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.Date;

import static cn.hutool.core.date.DatePattern.PURE_DATETIME_FORMAT;

/**
 * @author mqiqe
 */
@Primary
@Slf4j
@Service
public class MinioFileServiceImpl implements IFileService {
    @Autowired
    private FileProperties fileProperties;
    private MinioClient minioClient;
    private String bucket;
    private final RandomStringGenerator RSG = new RandomStringGenerator.Builder().withinRange('0', '9').get();
    @PostConstruct
    public void init() {
        try {
            minioClient = MinioClient.builder().endpoint(fileProperties.getUrl()).credentials(fileProperties.getAccessKey(), fileProperties.getSecretKey()).build();
            bucket = fileProperties.getBucket();
            BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucket).build();
            boolean isExist = minioClient.bucketExists(bucketExistsArgs);
            if (!isExist) {
                MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucket).build();
                minioClient.makeBucket(makeBucketArgs);
            }
        } catch (Exception e) {
            log.error("初始化Minio失败", e);
        }
    }

    @Override
    public boolean exits(String fileName) {
        try {
            StatObjectArgs statObjectArgs = StatObjectArgs.builder().bucket(bucket).object(fileName).build();
            minioClient.statObject(statObjectArgs);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public String upload(String newFileName, InputStream is) {
        // 上传
        String currTime = DateUtil.format(new Date(), PURE_DATETIME_FORMAT);
        String fileName = currTime + "/" + newFileName;
        // 如果存在重命名+4位随机数字
        if (exits(fileName)) {
            String suffix = newFileName.substring(newFileName.lastIndexOf("."));
            String oldName = newFileName.substring(0, newFileName.lastIndexOf("."));
            fileName = currTime + "/" + oldName + "_" + RSG.generate(6) + suffix;
        }
        try {
            // 判断是否是图片
            String suffer = StringUtils.substringAfterLast(newFileName, ".");
            PutObjectArgs putObjectArgs;
            if (StringUtils.containsAnyIgnoreCase(suffer, MimeTypeUtils.IMAGE_EXTENSION)) {
                long partSize = 64 * 1024 * 1024;
                putObjectArgs = PutObjectArgs.builder().bucket(bucket).object(fileName).contentType(MimeTypeUtils.getMineType(suffer)).stream(is, -1, partSize).build();
            } else {
                long partSize = 64 * 1024 * 1024;
                putObjectArgs = PutObjectArgs.builder().bucket(bucket).object(fileName).stream(is, -1, partSize).build();
            }
            minioClient.putObject(putObjectArgs);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return null;
        }
        return bucket + "/" + fileName;
    }

    public void remove(String bucketName, String objectName) {
        try {
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build();
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("删除文件失败", e);
        }
    }

    @Override
    public void remove(String path) {
        try {
            String[] split = path.split("/", 2);
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(split[0]).object(split[1]).build();
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("删除文件失败", e);
        }
    }

    @Override
    public String getWebUrl() {
        return fileProperties.getWebUrl();
    }

    @Override
    public InputStream getObject(String fileName) {
        try {
            if (Strings.CS.startsWith(fileName, bucket) || Strings.CS.startsWith(fileName, "/" + bucket)) {
                fileName = StringUtils.substringAfter(fileName, bucket);
            }
            GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucket).object(fileName).build();
            return minioClient.getObject(getObjectArgs);
        } catch (Exception e) {
            log.error("获取文件失败", e);
        }
        return null;
    }
}
